/*****************************************************************************
*    Ali Corp. All Rights Reserved. 2002 Copyright (C)
*
*    File:    hld_dev.c
*
*    Description:    This file contains all functions that implement
*		             HLD device management.
*    History:
*           Date            Athor        Version          Reason
*	    ============	=============	=========	=================
*	1.	Jan.26.2003      Justin Wu      Ver 0.1    Create file.
*	2.  Jan.17.2006      Justin Wu      Ver 0.2    Add get_dev_by_id().
*****************************************************************************/

#include <types.h>
#include <retcode.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <api/libc/alloc.h>
#include <hld/hld_dev.h>
#include <hld/decv/decv.h>
#include <osal/osal.h>
#include <hld/dis/VPO.h>
#include <hld/gma/gma.h>
#include <hld/snd/snd.h>
#include <bus/hdmi/m36/hdmi_api.h>
#include <api/libimagedec/imagedec.h>
#include <api/libmp/pe.h>
#include <hld/deca/deca.h>

#ifdef DUAL_ENABLE
#include <modules.h>

#ifdef MAIN_CPU
struct vdec_callback g_vdec_cb;
struct vpo_callback g_vpo_cb;
struct snd_callback g_snd_cb;
struct img_callback g_img_cb;
struct img_callback g_vde_cb;
struct img_callback g_mus_cb;
struct deca_callback g_deca_cb;
struct deca_data_callback g_deca_data_cb;
#endif


void remote_hld_dev_add(UINT8 *buf);
void remote_hld_dev_remove(UINT8 *buf);
void remote_hld_dev_memcpy(void *dest, const void *src, unsigned int len);
void remote_hld_see_init(void *addr);
void remote_cpy_from_priv_mem(void *dest);
#ifdef MAIN_CPU    
void hld_vdec_cb(UINT32 uParam);
void hld_vpo_cb(UINT32 uParam);
void hld_vpo_hdmi_cb(UINT32 uParam);
void hld_snd_hdmi_cb(UINT32 uParam);
void hld_snd_spec_cb(UINT32 uParam);
void hld_img_cb(unsigned long type, unsigned long param);
void hld_vde_cb(unsigned long type, unsigned long param);
void hld_mus_cb(unsigned long type, unsigned long param);
void hld_deca_cb(UINT32 uParam);
void hld_vdec_spec_cb(UINT32 uParam);
void hld_deca_data_cb(UINT32 uParam);
#endif

#if ((!defined _M3515_SECURE_BOOT_ENABLE_)||(!defined _BL_ENABLE_))
RET_CODE remote_hld_notify_see_trig(UINT32 param)
{
    return RET_FAILURE;
}

#else
UINT32 remote_hld_notify_see_trig(UINT32 param);
#endif

enum HLD_DECA_FUNC{
    FUNC_HLD_DEV_ADD = 0,   
    FUNC_HLD_DEV_REMOVE,   
    FUNC_HLD_MEM_CPY,
    FUNC_HLD_SEE_INIT,
    FUNC_CPY_FROM_PRIV_MEM,
    FUNC_HLD_NOTIFY_SEE_TRIG, 
    FUNC_HLD_OTP_GET_MUTEX, 
    FUNC_HLD_VDEC_CB,
    FUNC_HLD_VPO_CB,
    FUNC_HLD_VPO_HDMI_CB,
    FUNC_HLD_SND_HDMI_CB,
    FUNC_HLD_SND_SPEC_CB,
    FUNC_HLD_IMG_CB,
    FUNC_HLD_VDE_CB,
    FUNC_HLD_MUS_CB,
    FUNC_HLD_DECA_CB,
	FUNC_HLD_VDEC_SPEC_CB,
	FUNC_HLD_DECA_DATA_CB,

};

UINT32 hld_dev_entry[] = 
{
    (UINT32)remote_hld_dev_add,
    (UINT32)remote_hld_dev_remove,
    (UINT32)remote_hld_dev_memcpy,
    (UINT32)remote_hld_see_init,
    (UINT32)remote_cpy_from_priv_mem,
    (UINT32)remote_hld_notify_see_trig,
    (UINT32)remote_otp_get_mutex,
#ifdef MAIN_CPU    
    (UINT32)hld_vdec_cb,
    (UINT32)hld_vpo_cb,
    (UINT32)hld_vpo_hdmi_cb,
    (UINT32)hld_snd_hdmi_cb,
    (UINT32)hld_snd_spec_cb,
    (UINT32)hld_img_cb,
    (UINT32)hld_vde_cb,
    (UINT32)hld_mus_cb,
    (UINT32)hld_deca_cb,
	(UINT32)hld_vdec_spec_cb,
    (UINT32)hld_deca_data_cb,
#endif
};

UINT32 desc_hld_dev[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, sizeof(struct hld_device)),
  1, DESC_P_PARA(0, 0, 0), 
  //desc of pointer ret
  0,                          
  0,
};

#ifdef MAIN_CPU    
void hld_vdec_cb(UINT32 uParam)
{
    UINT8 type = uParam&0xff;
    UINT8 uParam1 = (uParam>>8)&0xff;
    UINT8 uParam2 = (uParam>>16)&0xff;
    switch(type)
    {
        case VDEC_CB_FIRST_SHOWED:
            if(g_vdec_cb.pcb_first_showed)
                g_vdec_cb.pcb_first_showed(uParam1, uParam2);
			break;
		case VDEC_CB_MODE_SWITCH_OK:
            if(g_vdec_cb.pcb_mode_switch_ok)
                g_vdec_cb.pcb_mode_switch_ok(uParam1, uParam2);
			break;
		case VDEC_CB_BACKWARD_RESTART_GOP: // used for advance play
		    if(g_vdec_cb.pcb_backward_restart_gop)
                g_vdec_cb.pcb_backward_restart_gop(uParam1, uParam2);
			break;
		case VDEC_CB_FIRST_HEAD_PARSED:
            if(g_vdec_cb.pcb_first_head_parsed)
                g_vdec_cb.pcb_first_head_parsed(uParam1, uParam2);
			break;
        case VDEC_CB_MONITOR_FRAME_VBV:
            if(g_vdec_cb.pcb_new_frame_coming)
                g_vdec_cb.pcb_new_frame_coming(uParam1, uParam2);
			break;
        case VDEC_CB_MONITOR_VDEC_START:
            if(g_vdec_cb.pcb_vdec_start)
                g_vdec_cb.pcb_vdec_start(uParam1, uParam2);
			break;
        case VDEC_CB_MONITOR_VDEC_STOP:
            if(g_vdec_cb.pcb_vdec_stop)
                g_vdec_cb.pcb_vdec_stop(uParam1, uParam2);
			break;
		default:
			break;
	}
}

void hld_vdec_spec_cb(UINT32 uParam)
{
    if(g_vdec_cb.pcb_vdec_user_data_parsed)
        g_vdec_cb.pcb_vdec_user_data_parsed(uParam, 0); 
}

void hld_vpo_cb(UINT32 uParam)
{
    UINT8 type = uParam&0xff;
    UINT8 uParam1 = (uParam>>8)&0xff;
    UINT8 uParam2 = (uParam>>16)&0xff;
    
    switch(type)
    {
        case VPO_CB_SRCASPRATIO_CHANGE:
            if(g_vpo_cb.pSrcAspRatioChange_CallBack)
                g_vpo_cb.pSrcAspRatioChange_CallBack(uParam1);
            break;
        default:
            break;
    }
}

void hld_vpo_hdmi_cb(UINT32 uParam)
{
    if(g_vpo_cb.phdmi_callback)
        g_vpo_cb.phdmi_callback(uParam);
}

void hld_snd_hdmi_cb(UINT32 uParam)
{
    if(g_snd_cb.phdmi_snd_cb)
        g_snd_cb.phdmi_snd_cb(uParam);
}

void hld_snd_spec_cb(UINT32 uParam)
{
    if(g_snd_cb.spec_call_back)
        g_snd_cb.spec_call_back((INT32 *)uParam);
}

void hld_img_cb(unsigned long type, unsigned long param)
{
    if(g_img_cb.mp_cb)
       g_img_cb.mp_cb(type, param); 
}

void hld_vde_cb(unsigned long type, unsigned long param)
{
    if(g_vde_cb.mp_cb)
       g_vde_cb.mp_cb(type, param);
}

void hld_mus_cb(unsigned long type, unsigned long param)
{
    if(g_mus_cb.mp_cb)
       g_mus_cb.mp_cb(type, param);
}

void hld_deca_cb(UINT32 uParam)
{
    UINT8 type = uParam&0xff;
    UINT8 uParam1 = (uParam>>8)&0xff;
    UINT8 uParam2 = (uParam>>16)&0xff;
/*
DECA_CB_MONITOR_NEW_FRAME = 0,
DECA_CB_MONITOR_START,
DECA_CB_MONITOR_STOP,
DECA_CB_MONITOR_DECODE_ERR,
DECA_CB_MONITOR_OTHER_ERR,
//////////////////////////////
DecaCBFunc pcb_output_new_frame;
DecaCBFunc pcb_deca_start;
DecaCBFunc pcb_deca_stop;
DecaCBFunc pcb_deca_decode_err;
DecaCBFunc pcb_deca_other_err;
*/
    switch(type)
    {
        case DECA_CB_MONITOR_NEW_FRAME:
            if(g_deca_cb.pcb_output_new_frame)
            {
                g_deca_cb.pcb_output_new_frame(uParam1, uParam2);
            }
            break;
        case DECA_CB_MONITOR_START:
            if(g_deca_cb.pcb_deca_start)
            {
                g_deca_cb.pcb_deca_start(uParam1, uParam2);
            }
            break;
        case DECA_CB_MONITOR_STOP:
            if(g_deca_cb.pcb_deca_stop)
            {
                g_deca_cb.pcb_deca_stop(uParam1, uParam2);
            }
            break;
        case DECA_CB_MONITOR_DECODE_ERR:
            if(g_deca_cb.pcb_deca_decode_err)
            {
                g_deca_cb.pcb_deca_decode_err(uParam1, uParam2);
            }
            break;
        case DECA_CB_MONITOR_OTHER_ERR:
            if(g_deca_cb.pcb_deca_other_err)
            {
               g_deca_cb.pcb_deca_other_err(uParam1, uParam2);
            }
            break;
        default:
            break;
    }
}

/*
* main cpu trig the see
*/
UINT32 hld_main_notify_see_trig(UINT32 param)
{
    jump_to_func(NULL, OS_hld_caller, param, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_NOTIFY_SEE_TRIG, NULL);
}
void hld_deca_data_cb(UINT32 uParam)
{
    struct DECA_FRAME_INFO *audio_frame_info = (struct DECA_FRAME_INFO *)uParam;
    
    switch(audio_frame_info->reg_cb_para.eCBType)
    {
        case DECA_CB_Announcement_Switching_Data_Field:
            if(g_deca_data_cb.pcb_deca_send_announcement_switching_data_field)
            {
                g_deca_data_cb.pcb_deca_send_announcement_switching_data_field((UINT32)(&audio_frame_info->anci_data),(UINT32)(&audio_frame_info->reg_cb_para));
            }
            break;
        default:
            break;
    }
    
}

#endif

void hld_base_callee(UINT8 *msg)
{
    OS_hld_callee((UINT32)hld_dev_entry, msg);
}

INT32 hld_dev_add_remote(struct hld_device *dev, UINT32 dev_addr)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_BASE_MODULE<<24)|(2<<16)|FUNC_HLD_DEV_ADD, desc_hld_dev);
}

INT32 hld_dev_remove_remote(struct hld_device *dev)
{
    jump_to_func(NULL, OS_hld_caller, dev, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_DEV_REMOVE, desc_hld_dev);
}

void hld_dev_memcpy(void *dest, const void *src, unsigned int len)
{
    jump_to_func(NULL, OS_hld_caller, dest, (HLD_BASE_MODULE<<24)|(3<<16)|FUNC_HLD_MEM_CPY, NULL);
}

void copy_from_priv_mem(void *dest, UINT32 data_len)
{
    UINT32 desc[] = {1, DESC_OUTPUT_STRU(0, 64),1, DESC_P_PARA(0, 0, 0), 0, 0,};
    jump_to_func(NULL, OS_hld_caller, dest, (HLD_BASE_MODULE<<24)|(2<<16)|FUNC_CPY_FROM_PRIV_MEM, desc);
}

void hld_otp_get_mutex(UINT32 flag)
{
    jump_to_func(NULL, OS_hld_caller, flag, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_OTP_GET_MUTEX, NULL);
}

void hld_dev_see_init(void *addr)
{
	jump_to_func(NULL, OS_hld_caller, addr, (HLD_BASE_MODULE << 24) | (1 << 16) 
		| FUNC_HLD_SEE_INIT, NULL);
}


#define DRAM_SPLIT_CTRL_BASE 0xb8041000
#define PVT_S_ADDR 0x10
//This function set data into private memory
//in_data: the address for the data which need set into the private memory
//data_len: the Max length can support 64bytes
UINT32 store_data(UINT8 *in_data,UINT32 data_len)
{
    UINT32 priv_base_addr=0;
	UINT8* dest;
	
    priv_base_addr = *(volatile UINT32 *)(DRAM_SPLIT_CTRL_BASE+PVT_S_ADDR);
    if(priv_base_addr==0)
    {
        //libc_printf("the private memory not set!\n");
        return 0;
    }
    else
    {
        if(data_len>64)
        {
            data_len= 64;
        }
        priv_base_addr |=(0xa<<28);
		//libc_printf("MEMCPY: dest=0x%x,src=0x%x,len=%d\n", (priv_base_addr+0x80),in_data,data_len);
		dest=priv_base_addr+0x80;
        osal_cache_flush((void*)(in_data), data_len);
        if(*(unsigned char *)(in_data+data_len-1) != *(volatile unsigned char*)((UINT32)(in_data+data_len-1)|0xa0000000))
        {
			//libc_printf("len=%d\n", data_len);
            //make sure data is flushed into cache before send to SEE
            ASSERT(0);
        }
		//libc_printf("hld_dev_memcpy:dest=0x%x,src=0x%x,len=%d\n", dest, ((UINT32)(in_data)&0xfffffff)|0xa0000000, data_len);
  	    hld_dev_memcpy(dest, ((UINT32)(in_data)&0xfffffff)|0xa0000000, data_len);

		return data_len;
    }
}

//This function get some data from private memory
//out_data: the address for the data which need get from the private memory
//data_len: the Max length can support 64bytes
UINT32 get_data(UINT8 *out_data,UINT32 data_len)
{
    copy_from_priv_mem(out_data,data_len);
	if(data_len>64)
	{
		data_len= 64;
	}
	return data_len;
}

#ifdef SEE_CPU
UINT32 desc_vpo_hdmi_cb[] = 
{ //desc of pointer para
//  1, DESC_OUTPUT_STRU(0, sizeof(struct de2Hdmi_video_infor)),
  1, DESC_STATIC_STRU(0, sizeof(struct de2Hdmi_video_infor)),
  1, DESC_P_PARA(0, 0, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 desc_snd_hdmi_cb[] = 
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, sizeof(struct snd2Hdmi_audio_infor)),
  1, DESC_P_PARA(0, 0, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 desc_vdec_cb[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, sizeof(struct user_data_pram)),
  1, DESC_P_PARA(0, 0, 0), 
  //desc of pointer ret
  0,                          
  0,
};

#if 0
void hld_cpu_callback(UINT32 uParam)
{
    jump_to_func(NULL, OS_hld_caller, uParam, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_VDEC_CB, NULL);
}

void hld_cpu_vpo_callback(UINT32 uParam)
{
    jump_to_func(NULL, OS_hld_caller, uParam, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_VPO_CB, NULL);
}

void hld_cpu_hdmi_callback(UINT32 uParam)
{
    jump_to_func(NULL, OS_hld_caller, uParam, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_VPO_HDMI_CB, desc_vpo_hdmi_cb);
}

void hld_cpu_snd_callback(UINT32 uParam)
{
    jump_to_func(NULL, OS_hld_caller, uParam, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_SND_HDMI_CB, desc_snd_hdmi_cb);
}

#else

void hld_cpu_os_callback(UINT32 uParam)
{
    jump_to_func(NULL, OS_hld_caller, uParam, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_VDEC_CB, NULL);
}

void hld_cpu_os_vpo_callback(UINT32 uParam)
{
    jump_to_func(NULL, OS_hld_caller, uParam, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_VPO_CB, NULL);
}

void hld_cpu_os_hdmi_callback(UINT32 uParam)
{
    jump_to_func(NULL, OS_hld_caller, uParam, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_VPO_HDMI_CB, desc_vpo_hdmi_cb);
}

void hld_cpu_os_vdec_spec_callback(UINT32 uParam)
{
    jump_to_func(NULL, OS_hld_caller, uParam, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_VDEC_SPEC_CB, desc_vdec_cb);
}

void hld_cpu_os_snd_callback(UINT32 uParam)
{
    jump_to_func(NULL, OS_hld_caller, uParam, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_SND_HDMI_CB, desc_snd_hdmi_cb);
}

void hld_cpu_os_snd_spec_callback(UINT32 uParam)
{
    jump_to_func(NULL, OS_hld_caller, uParam, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_SND_SPEC_CB, NULL);
}

void hld_cpu_img_cb(unsigned long type, unsigned long param)
{
    jump_to_func(NULL, OS_hld_caller, type, (HLD_BASE_MODULE<<24)|(2<<16)|FUNC_HLD_IMG_CB, NULL);
}

void hld_cpu_vde_cb(unsigned long type, unsigned long param)
{
    jump_to_func(NULL, OS_hld_caller, type, (HLD_BASE_MODULE<<24)|(2<<16)|FUNC_HLD_VDE_CB, NULL);
}

void hld_cpu_mus_cb(unsigned long type, unsigned long param)
{
    jump_to_func(NULL, OS_hld_caller, type, (HLD_BASE_MODULE<<24)|(2<<16)|FUNC_HLD_MUS_CB, NULL);
}

void hld_cpu_os_deca_cb(UINT32 uParam)
{
    jump_to_func(NULL, OS_hld_caller, uParam, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_DECA_CB, NULL);
}
void hld_cpu_os_deca_data_cb(UINT32 uParam)
{
    struct DECA_FRAME_INFO *audio_frame_info = (struct DECA_FRAME_INFO *)uParam;
    UINT32 desc_deca_frame_information_cb[] = 
    { //desc of pointer para
      1, DESC_OUTPUT_STRU(0, sizeof(struct DECA_FRAME_INFO)),
      1, DESC_P_PARA(0, 0, 0),//desc of pointer ret
      0,
      0,
    };
    jump_to_func(NULL, OS_hld_caller, uParam, (HLD_BASE_MODULE<<24)|(1<<16)|FUNC_HLD_DECA_DATA_CB, desc_deca_frame_information_cb);
}    
void hld_cpu_callback(UINT32 uParam)
{
    os_remote_cb_send_msg(hld_cpu_os_callback, uParam);
}

void hld_cpu_vpo_callback(UINT32 uParam)
{
    os_remote_cb_send_msg(hld_cpu_os_vpo_callback, uParam);
}

void hld_cpu_hdmi_callback(UINT32 uParam)
{
    os_remote_cb_send_msg(hld_cpu_os_hdmi_callback, uParam);
}

void hld_cpu_vdec_spec_callback(UINT32 uParam)
{
    os_remote_cb_send_msg(hld_cpu_os_vdec_spec_callback, uParam);
}

void hld_cpu_snd_callback(UINT32 uParam)
{
    os_remote_cb_send_msg(hld_cpu_os_snd_callback, uParam);
}

void hld_cpu_snd_spec_callback(UINT32 uParam)
{
    os_remote_cb_send_msg(hld_cpu_os_snd_spec_callback, uParam);
}

void hld_cpu_deca_cb(UINT32 uParam)
{
    os_remote_cb_send_msg(hld_cpu_os_deca_cb, uParam);
}

void hld_cpu_deca_data_cb(UINT32 uParam)
{
    os_remote_cb_send_msg(hld_cpu_os_deca_data_cb, uParam);
}
#endif

#endif

#endif

